1 module unde.games.dizzy.omega.dog; 2 3 import derelict.opengl3.gl; 4 5 import std.algorithm; 6 import std.conv; 7 import std.math; 8 import std.stdio; 9 import unde.games.dizzy.omega.main; 10 import unde.games.dizzy.omega.rope; 11 import unde.games.object; 12 import unde.games.renderer; 13 import unde.games.collision_detector; 14 import unde.games.object; 15 import unde.global_state; 16 17 class Dog:StaticGameObject 18 { 19 static int num; 20 int number; 21 22 int hidden; 23 24 enum SPEED = 0.1; 25 enum MAX_V = 0.3; 26 enum A = 0.01; 27 enum STATE 28 { 29 WATCH, 30 GO_UP, 31 GO_RIGHT, 32 CLOSE_MOUTH, 33 GO_LEFT, 34 GO_DOWN, 35 OPEN_MOUTH, 36 FLY_AWAY, 37 } 38 39 STATE state; 40 41 float def_x, def_y, def_z; 42 float dx = 0.0, dy = 0.0; 43 long frame; 44 long start_anim; 45 int mouth; 46 47 Rope rope; 48 49 LiveGameObject the_hero; 50 51 bool search_surface; 52 static GLuint rope_texture; 53 54 this(MainGameObject root, float[3] coords, float[3] rope_start, float by, uint length, float segl, LiveGameObject hero) 55 { 56 def_x = x = coords[0]; 57 def_y = y = coords[1]; 58 def_z = z = coords[2]; 59 the_hero = hero; 60 number = num++; 61 models["dog"] = root.models["dog"]; 62 //collision_objects["solid"] = root.collision_objects["solid"]; 63 64 rope = new Rope(root, rope_start, [x-1.4, y, z], by, length, segl); 65 66 super(root); 67 } 68 69 void cut_rope() 70 { 71 rope.cut(2); 72 } 73 74 bool fly_anim(GlobalState gs, string name) 75 { 76 float f = (frame*4)%240; 77 float degree = 0.0; 78 float translate = 0.0; 79 80 if (f < 120.0) 81 translate = 0.2 - 0.4*f/120.0; 82 else if (f < 240.0) 83 translate = -0.2 + 0.4*(f - 120.0)/120.0; 84 85 if (f < 120.0) 86 degree = f/2 - 30.0; 87 else if (f < 240.0) 88 degree = 30.0 - (f/2 - 60.0); 89 90 glTranslatef(0.0, translate, 0.0); 91 92 if (name == "Dog-LeftWing") 93 { 94 glTranslatef(0.0, 0.4, 0.5); 95 glRotatef(degree, 1.0, 0.0, 0.0); 96 glTranslatef(0.0, -0.4, -0.5); 97 } 98 99 if (name == "Dog-RightWing") 100 { 101 glTranslatef(0.0, 0.4, -0.5); 102 glRotatef(-degree, 1.0, 0.0, 0.0); 103 glTranslatef(0.0, -0.4, 0.5); 104 } 105 106 if (name.startsWith("Dog-Head")) 107 { 108 if ((name[8] - '1') != mouth) 109 { 110 return false; 111 } 112 } 113 114 return true; 115 } 116 117 void hide() 118 { 119 hidden++; 120 } 121 122 override void draw(GlobalState gs) 123 { 124 if ( abs(root.scrx-x) > 16.0 && 125 abs(root.scrx-def_x) > 16.0 || 126 abs(root.scry-y) > 9.0 ) 127 return; 128 129 if (!hidden) 130 { 131 glPushMatrix(); 132 glTranslatef(x, y, z); 133 if (dx > 0.0) glRotatef(180,0,1,0); 134 recursive_render(gs, models["dog"], &fly_anim); 135 glPopMatrix(); 136 137 rope.draw(gs); 138 } 139 else if (hidden == 1) 140 { 141 rope.draw_part(gs, 0, rope.cut_segm); 142 } 143 } 144 145 immutable float side_sensor_dx = 1.0; 146 immutable float[2] side_sensor_y = [0.5, 0.8]; 147 148 immutable float bottom_sensor_dx = 0.6; 149 immutable float bottom_sensor_dy = 0.5; 150 151 override bool tick(GlobalState gs) 152 { 153 if ( hidden || abs(root.scrx-x) > 16.0 && 154 abs(root.scrx-def_x) > 16.0 || 155 abs(root.scry-y) > 9.0 ) 156 return true; 157 158 float speedfactor = 1.0; 159 160 if (state != STATE.FLY_AWAY) 161 { 162 if (the_hero.x < x) 163 { 164 speedfactor = 0.5; 165 } 166 else if (the_hero.x < x+1.5) 167 { 168 speedfactor = the_hero.x - x; 169 } 170 else 171 speedfactor = 2.0; 172 } 173 174 frame++; 175 x += dx * speedfactor; 176 y += dy * speedfactor; 177 178 final switch (state) 179 { 180 case STATE.WATCH: 181 float dhy = the_hero.y + 1.0 - y; 182 if (dhy > 0.0 && dy < dhy/2.0 && dy < MAX_V) 183 dy += A; 184 else if (dhy < 0.0 && dy > dhy/2.0 && dy > -MAX_V) 185 dy -= A; 186 else dy = 0.0; 187 188 if (the_hero.x + 4.5 > x) 189 the_hero.x = x - 4.5; 190 191 if (abs(the_hero.x - x) < 7.0) 192 { 193 long f = frame%200; 194 if (f < 10) 195 mouth = 1; 196 else if (f < 20) 197 mouth = 0; 198 else if (f < 30) 199 mouth = 1; 200 else if (f < 40) 201 mouth = 2; 202 else if (f < 50) 203 mouth = 1; 204 else if (f < 60) 205 mouth = 0; 206 else if (f < 70) 207 mouth = 1; 208 else 209 mouth = 2; 210 } 211 else mouth = 2; 212 213 DizzyOmega dz = cast(DizzyOmega) root; 214 if (dz.dizzy_throw_branch_quest_state == 2) 215 { 216 mouth = 2; 217 dx = 0.000001; 218 dy = SPEED; 219 state = STATE.GO_UP; 220 } 221 222 if (rope.cut_segm >= 0) 223 { 224 dx = -SPEED*1.5; 225 dy = SPEED*1.5/10; 226 z = -2.0; 227 state = STATE.FLY_AWAY; 228 } 229 230 break; 231 232 case STATE.GO_UP: 233 if (y > 0.9) 234 { 235 state = STATE.GO_RIGHT; 236 dy = 0; 237 dx = SPEED; 238 } 239 break; 240 241 case STATE.GO_RIGHT: 242 if (x > 364.5) 243 { 244 state = STATE.CLOSE_MOUTH; 245 start_anim = frame; 246 dy = 0; 247 dx = 0.00001; 248 } 249 else if (x > 364.2) 250 { 251 mouth = 0; 252 } 253 else if (x > 364.0) 254 { 255 mouth = 1; 256 } 257 258 break; 259 260 case STATE.CLOSE_MOUTH: 261 long f = frame - start_anim; 262 if (f < 10) 263 { 264 mouth = 1; 265 dx = -SPEED; 266 dy = 0; 267 state = STATE.GO_LEFT; 268 } 269 break; 270 271 case STATE.GO_LEFT: 272 if (x <= def_x) 273 { 274 state = STATE.GO_DOWN; 275 dx = 0; 276 dy = -SPEED; 277 } 278 break; 279 280 case STATE.GO_DOWN: 281 if (y <= def_y) 282 { 283 state = STATE.OPEN_MOUTH; 284 start_anim = frame; 285 dx = 0; 286 dy = 0; 287 } 288 break; 289 290 case STATE.OPEN_MOUTH: 291 long f = frame - start_anim; 292 if (f < 20) 293 { 294 mouth = 0; 295 } 296 else if (f < 30) 297 { 298 mouth = 1; 299 } 300 else if (f < 40) 301 { 302 mouth = 2; 303 if (rope.cut_segm < 0) 304 state = STATE.WATCH; 305 else 306 { 307 dx = -SPEED*1.5; 308 dy = SPEED*1.5/10; 309 z = -2.0; 310 state = STATE.FLY_AWAY; 311 } 312 } 313 break; 314 case STATE.FLY_AWAY: 315 if (x < 270.0) 316 { 317 state = STATE.WATCH; 318 hide(); 319 } 320 } 321 322 if (rope.rope.length > 1) 323 { 324 float f = (frame*4)%240; 325 float translate = 0.0; 326 327 if (f < 120.0) 328 translate = 0.2 - 0.4*f/120.0; 329 else if (f < 240.0) 330 translate = -0.2 + 0.4*(f - 120.0)/120.0; 331 332 rope.rope[$-1] = [x-1.4, y+translate, z]; 333 rope.tick(gs); 334 } 335 336 return true; 337 } 338 339 override void load(string[string] s) 340 { 341 string p = "dog"~number.to!(string); 342 if (p~"-x" in s) 343 x = s[p~"-x"].to!(float); 344 else 345 x = def_x; 346 347 if (p~"-y" in s) 348 y = s[p~"-y"].to!(float); 349 else 350 y = def_y; 351 352 if (p~"-z" in s) 353 z = s[p~"-z"].to!(float); 354 else 355 z = def_z; 356 357 if (p~"-dx" in s) 358 dx = s[p~"-dx"].to!(float); 359 else 360 dx = 0.0; 361 362 if (p~"-dy" in s) 363 dy = s[p~"-dy"].to!(float); 364 else 365 dy = 0.0; 366 367 if (p~"-state" in s) 368 state = s[p~"-state"].to!(STATE); 369 else 370 state = STATE.WATCH; 371 372 if (p in s) 373 { 374 hidden = (s[p] == "hidden-rope")?2:(s[p] == "hidden")?1:0; 375 } 376 else 377 { 378 hidden = 0; 379 } 380 381 rope.rope[$-1] = [x-1.4, y, z]; 382 rope.load(s); 383 } 384 385 override void save(ref string[string] s) 386 { 387 string p = "dog"~number.to!(string); 388 if (hidden == 1) 389 s[p] = "hidden"; 390 else if (hidden == 2) 391 s[p] = "hidden-rope"; 392 393 s[p~"-x"] = x.to!(string); 394 s[p~"-y"] = y.to!(string); 395 s[p~"-z"] = z.to!(string); 396 s[p~"-dx"] = dx.to!(string); 397 s[p~"-dy"] = dy.to!(string); 398 s[p~"-state"] = state.to!(string); 399 400 rope.save(s); 401 } 402 } 403